#pragma once

#include "noncopyable.h"
#include "Timestamp.h"

#include <functional>
#include <memory>

/*
    channel 封装了socket,用来管理感兴趣的事件(event) 如epollin epollout
    还绑定了poller 返回的具体事件
*/

class EventLoop;

class Channel : noncopyable
{
public:
    using EventCallback = std::function<void()>;
    using ReadCallback = std::function<void(Timestamp)>;

    Channel(EventLoop *loop, int fd);
    ~Channel();

    // fd得到poller通知之后，处理事件的
    void handleEvent(Timestamp receiveTime);

    // 设置回调函数对象
    void setReadCallback(ReadCallback cb) { readCallback_ = std::move(cb); }
    void setWriteCallback(EventCallback cb) { writeCallback_ = std::move(cb); }
    void setCloseCallbck(EventCallback cb) { closeCallback_ = std::move(cb); }
    void setErrorCallback(EventCallback cb) { errorCallback_ = std::move(cb); }

    // 防止channel手动被remoce掉，还在执行回调操作
    void tie(const std::shared_ptr<void> &);

    int fd() const { return fd_; }
    int events() const { return events_; }
    void set_revents(int revt) { revents_ = revt; }

    int index() const { return index_; }
    void set_index(int idx) { index_ = idx; }

    bool isNoneEvent() const { return events_ == KNoneEvent; }

    // 让fd 对读/写事件感兴趣 upodate() 通知epollctl将感兴趣的事件添加到epoll中
    void enableReading()
    {
        events_ |= KReadEvent;
        update();
    }
    void disableReading()
    {
        events_ &= ~KReadEvent;
        update();
    }
    void enableWriting()
    {
        events_ |= KWriteEvent;
        update();
    }
    void disableWriting()
    {
        events_ &= ~KWriteEvent;
        update();
    }
    void disableAll()
    {
        events_ = KNoneEvent;
        update();
    }
    bool isWriting() const { return events_ & KWriteEvent; }
    bool isReading() const { return events_ & KReadEvent; }

    // one loop per thread
    EventLoop *onwerLoop() { return loop_; }
    void remove();

private:
    void update();
    void handlerEventWithGuard(Timestamp receiveTime);

    static const int KNoneEvent;  // 没有任何事件
    static const int KReadEvent;  // 读事件
    static const int KWriteEvent; // 写事件

    EventLoop *loop_; // 事件循环
    const int fd_;    // poller_监听的fd
    int events_;      // 注册fd感兴趣的事件
    int revents_;     // poller返回的是具体发送的事件
    int index_;       // 被poller使用

    std::weak_ptr<void> tie_;
    bool tied_;

    bool eventHandling; // 确保析构的时候没有处理的回调操作

    // 因为channel能够知道fd最终发送的具体的时间revents，所以它负载调用具体的事件回调
    ReadCallback readCallback_;
    EventCallback writeCallback_;
    EventCallback closeCallback_;
    EventCallback errorCallback_;
};